package com.example.controller;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.Service.AccountService;
import com.example.entity.RestBean;
import com.example.entity.vo.request.EmailRegisterVo;
import com.example.entity.vo.request.EmailResetVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.Pattern;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 作者:xuSen
 * 日期2025/4/17 12:20
 */
@Validated
@RestController
@RequestMapping("/api/auth")
public class AuthorizeController {
    @Resource
    private AccountService accountService;

    /**
     * 处理发送验证码请求的控制器方法
     * 该方法响应GET请求，并根据用户提供的邮箱和类型发送相应的验证码
     *
     * @param email   用户输入的电子邮箱地址，使用@Email注解进行格式验证
     * @param type    请求类型，可以是"register"（注册）或"reset"（重置密码），使用@Pattern注解进行验证
     * @param request HttpServletRequest对象，用于获取请求的远程地址
     * @return 返回一个RestBean对象，包含执行结果，此处泛型为Void，表示不返回具体数据
     */
    @GetMapping("/ask-code")
    public RestBean<Void> askCode(@RequestParam @Email String email,
                                  @RequestParam @Pattern(regexp = "(register|reset|modify)") String type,
                                  HttpServletRequest request) {
//        // 调用服务层方法生成验证码并发送到指定邮箱
//        String massage = accountService.registerEmailVerifyCode(type, email, request.getRemoteAddr());
//        // 根据返回的消息判断验证码发送是否成功
//        if(massage == null)
//            // 如果没有错误消息，表示发送成功，返回成功信息
//            return RestBean.success();
//        else
//            // 如果有错误消息，表示发送失败，返回错误信息和状态码400
//            return RestBean.failure(400,massage);
        // 调用messageHandle方法处理发送验证码的逻辑，传入类型、邮箱和请求的远程地址作为参数
        return messageHandle(() -> accountService.registerEmailVerifyCode(type, email, request.getRemoteAddr()));
    }

    /**
     * 处理用户使用电子邮件注册的请求
     * 此方法通过POST请求接收用户信息，并调用账户服务进行注册
     *
     * @param registerVo 包含用户注册信息的EmailRegisterVo对象，包括电子邮件、密码等
     *                   该对象通过@Validated注解进行参数校验，确保数据完整性
     * @return 返回一个RestBean<Void>对象，表示注册操作的结果
     * RestBean封装了操作状态和可能的错误信息，便于前端处理
     */
    @PostMapping("/register")
    public RestBean<Void> register(@RequestBody @Validated EmailRegisterVo registerVo) {
//        // 调用服务层方法进行注册操作，传入注册信息
//        String massage = accountService.registerEmailAccount(registerVo);
//        // 根据返回的消息判断注册是否成功
//        if(massage == null)
//            // 如果没有错误消息，表示注册成功，返回成功信息
//            return RestBean.success();
//        else
//            // 如果有错误消息，表示注册失败，返回错误信息和状态码400
//            return RestBean.failure(400,massage);

        // 调用消息处理方法执行账户注册逻辑，将用户注册信息作为参数传递
//        return messageHandle(() -> accountService.registerEmailAccount(registerVo));
        return messageHandle(registerVo, accountService::registerEmailAccount);
    }

    @PostMapping("/reset-confirm")
    public RestBean<Void> resetConfirm(@RequestBody @Validated com.example.entity.vo.request.ConfirmResetVO confirmResetVO) {
//        // 调用账户服务进行密码重置确认操作，传入确认信息
//        String massage = accountService.resetConfirm(confirmResetVO);
//        // 根据返回的消息判断操作是否成功
//        if(massage == null)
//            // 如果没有错误消息，表示操作成功，返回成功信息
//            return RestBean.success();
//        else
//        // 如果有错误消息，表示操作失败，返回错误信息和状态码400
//            return RestBean.failure(400,massage);

        // 调用消息处理方法执行密码重置确认逻辑，将确认信息作为参数传递
//        return messageHandle(() -> accountService.resetConfirm(confirmResetVO));
        return messageHandle(confirmResetVO, accountService::resetConfirm);
    }

    /**
     * 处理密码重置请求的端点
     * 该方法使用POST请求接收包含邮箱重置信息的JSON对象，并调用账户服务进行密码重置操作
     *
     * @param emailResetVO 包含邮箱重置信息的VO对象，包括验证码、新密码等信息
     * @return 返回一个RestBean对象，表示密码重置操作的结果
     */
    @PostMapping("/reset-password")
    public RestBean<Void> resetConfirm(@RequestBody @Validated EmailResetVO emailResetVO) {
        // 调用账户服务进行密码重置操作，传入重置信息
//        return messageHandle(() -> accountService.resetEmailAccountPassword(emailResetVO));
        return messageHandle(emailResetVO, accountService::resetEmailAccountPassword);
    }

    /**
     * 处理消息的通用方法
     *
     * 该方法通过接受一个泛型参数和一个函数式接口参数，来实现对不同类型的请求数据进行处理
     * 它的主要作用是将业务逻辑中处理消息的部分抽象出来，以便在不同的上下文中复用
     *
     * @param <T> 泛型参数，表示可以接受任何类型的对象
     * @param vo 请求数据对象，可以是任何类型，代表了请求中的数据
     * @param function 函数式接口参数，它接受一个泛型参数并返回一个字符串，代表了具体的业务处理逻辑
     * @return 返回一个RestBean对象，其中包含了处理结果
     */
    private <T> RestBean<Void> messageHandle(T vo, Function<T,String> function) {
        // 调用另一个重载的messageHandle方法，传入一个 Supplier 函数式接口的实现
        // 该实现通过调用传入的Function接口，将vo对象转换为字符串，作为消息处理的输入
        return messageHandle(()->function.apply(vo));
    }
    /**
     * 处理消息的通用方法
     * 该方法通过接受一个Supplier函数式接口的实现来获取消息，并根据消息的内容决定返回成功还是失败的响应
     * 主要用于简化消息处理逻辑，统一处理格式
     *
     * @param supplier 函数式接口，用于提供消息字符串
     * @return RestBean<Void> 返回一个表示操作结果的RestBean对象，无具体返回内容
     */
    private RestBean<Void> messageHandle(Supplier<String> supplier) {
        // 获取供应商提供的消息
        String massage = supplier.get();
        // 如果消息为空，表示操作成功
        if (massage == null)
            return RestBean.success();
            // 如果消息不为空，表示操作失败，返回错误码400和错误信息
        else
            return RestBean.failure(400, massage);
    }

}
